package main

import (
	"fmt"
	"io"
	"net"
	"sync"
)

type Server struct {
	Ip   string
	Port int

	//在线用户
	OnlineMap map[string]*User
	mapLock sync.RWMutex

	Message chan string
}

//创建server接口
func NewServer(ip string, port int) *Server {

	server := &Server{
		Ip:   ip,
		Port: port,
		OnlineMap: make(map[string]*User),
		Message: make(chan string),
	}
	return server
}

//监听Message广播消息channel的goroutine，一旦有消息就发送给全部的在线User
func (s *Server) ListenMessage()  {

	for {
		msg := <- s.Message
		s.mapLock.Lock()
		for _, user := range s.OnlineMap {
			user.C <-msg
		}
		s.mapLock.Unlock()
	}
}

//广播消息的方法
func (s *Server) BroadCast(user *User, msg string)  {
	sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg
	s.Message <- sendMsg
}

func (s *Server) handle(con net.Conn) {

	user := NewUser(con)

	s.mapLock.Lock()
	s.OnlineMap[user.Name] = user
	s.mapLock.Unlock()

	s.BroadCast(user, "已上线")

	go func() {
		buf := make([]byte, 4096)
		for  {
			n, err := con.Read(buf)
			if n == 0 {
				s.BroadCast(user, "下线")
				return
			}
			if err != nil && err != io.EOF {
				fmt.Println("con.read err : ", err)
				return
			}
			msg := string(buf[:n-1])
			s.BroadCast(user, msg)
		}

	}()

	select {}
}


func (s *Server) Start() {

	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Ip, s.Port))

	if err != nil {
		fmt.Println("net.listen err:", err)
		return
	}
	defer listen.Close()

	go s.ListenMessage()

	for {

		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("listen.accept err :", err)
			continue
		}

		go s.handle(conn)
	}
	
}
